//VMwareCandidates
//
//Copyright (C) 8/13/2007 Joseph Lee Callen
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace VMwareCandidates
{
    public class ServerMonitoring
    {
        /* Every five minutes get a average sample for a 72 hour period.
         * Each will have there own thread to operate on sample data
         */
        private System.Threading.Thread[] threadArray;
        private int operationCount = 0;
        private Object oThreadLock = new Object();

        public ServerMonitoring(Object[] oArray)
        {
            //number of server to monitor and the number of threads to create
            //threadArray = new System.Threading.Thread(oArray.Length

            int maxThreads = oArray.Length;
            threadArray = new System.Threading.Thread[maxThreads];
            for (int count = 0; count < maxThreads; count++)
            {
                if (AddServerToDatabase((string)oArray[count]) == true)
                {
                    threadArray[count] = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(ThreadServerMonitor));
                    threadArray[count].Start(oArray[count]);
                }
            }
        }
        public void KillServerMonitoringThreads()
        {
            if (threadArray != null)
            {
                foreach (System.Threading.Thread kThread in threadArray)
                {
                    try
                    {
                        switch (kThread.ThreadState)
                        {
                            case System.Threading.ThreadState.Running:
                                kThread.Abort();
                                break;
                            case System.Threading.ThreadState.Background:
                                kThread.Abort();
                                break;
                            case System.Threading.ThreadState.Suspended:
                                kThread.Abort();
                                break;
                            case System.Threading.ThreadState.WaitSleepJoin:
                                kThread.Abort();
                                break;
                            default:
                                break;
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.Error.WriteLine(ex.Message);
                    }
                }
            }
        }


        private bool AddServerToDatabase(string name) 
        {

            VMwareCandidateDataSetTableAdapters.CANDIDATESTableAdapter candidatesTA 
                = new VMwareCandidates.VMwareCandidateDataSetTableAdapters.CANDIDATESTableAdapter();
            VMwareCandidateDataSetTableAdapters.HARDWARETableAdapter hardwareTA 
                = new VMwareCandidates.VMwareCandidateDataSetTableAdapters.HARDWARETableAdapter();

            VMwareCandidateDataSet.CANDIDATESDataTable candidatesDT = new VMwareCandidateDataSet.CANDIDATESDataTable();
            VMwareCandidateDataSet.HARDWAREDataTable hardwareDT = new VMwareCandidateDataSet.HARDWAREDataTable();

            candidatesTA.Fill(candidatesDT);
            hardwareTA.Fill(hardwareDT);

            StringBuilder sbFilter = new StringBuilder();
            sbFilter.AppendFormat("NAME = \'{0}\'", name);

            System.Data.DataRow[] drCandidates = candidatesDT.Select(sbFilter.ToString());

            if (drCandidates.Length == 0)
            {
                try
                {
                    WMIQuery newserver_query = new WMIQuery(name, true, true, false, true, false, false, false, false, false, false, false);

                    if (newserver_query.Access == false)
                    {
                        return false;
                    }

                    StringBuilder sbInsertQuery = new StringBuilder();
                    sbInsertQuery.AppendFormat(
                        "INSERT INTO HARDWARE (PROCESSOR,MHZ,NUM_OF_PROC,RAM,DISKUSED) VALUES (\'{0}\',{1},{2},{3},{4});SELECT @@identity",
                        newserver_query.ProcModel,
                        (int)newserver_query.MHz,
                        newserver_query.NumOfProcs,
                        (int)newserver_query.RAM,
                        (int)(newserver_query.TotalHD - newserver_query.FreeSpace));
                    string query = sbInsertQuery.ToString();

                    hardwareTA.Connection.Open();
                    System.Data.SqlClient.SqlCommand identity = new System.Data.SqlClient.SqlCommand(query, hardwareTA.Connection);
                    decimal hardwareID = (decimal)identity.ExecuteScalar();
                    hardwareTA.Connection.Close();

                    try
                    {
                        System.Net.NetworkInformation.Ping p = new System.Net.NetworkInformation.Ping();
                        System.Net.NetworkInformation.PingReply pr = p.Send(name);
                        pr.Address.ToString();

                        System.Net.IPHostEntry iphost = System.Net.Dns.GetHostEntry(name);
                        candidatesTA.Insert(name, pr.Address.ToString(), iphost.HostName, (int)hardwareID);
                    }
                    catch (Exception e)
                    {
                        Console.Error.WriteLine(e.Message);
                        candidatesTA.Insert(name, "unknown", "unknown", (int)hardwareID);
                        return false;
                    }   
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine(ex.Message);
                    return false;
                }
            }
            return true;
        }
        private void ThreadServerMonitor(object candidate)
        {
            while (true)
            {
                try
                {
                    WMIQuery wmiquery = new WMIQuery((string)candidate, false, false, false, false, false, false, false, true, true, true, true);
                    //WMIQuery wmiquery = new WMIQuery((string)candidate, false, false, false, false, false, false, false, false, true, false, false);
                    if (wmiquery.Access)
                    {
                        VMwareCandidateDataSetTableAdapters.CANDIDATESTableAdapter candidatesTA
                            = new VMwareCandidates.VMwareCandidateDataSetTableAdapters.CANDIDATESTableAdapter();
                        VMwareCandidateDataSetTableAdapters.CPUTableAdapter cpuTA
                            = new VMwareCandidates.VMwareCandidateDataSetTableAdapters.CPUTableAdapter();
                        VMwareCandidateDataSetTableAdapters.DISKTableAdapter diskTA
                            = new VMwareCandidates.VMwareCandidateDataSetTableAdapters.DISKTableAdapter();
                        VMwareCandidateDataSetTableAdapters.MEMORYTableAdapter memoryTA
                            = new VMwareCandidates.VMwareCandidateDataSetTableAdapters.MEMORYTableAdapter();
                        VMwareCandidateDataSetTableAdapters.NETWORKTableAdapter networkTA
                            = new VMwareCandidates.VMwareCandidateDataSetTableAdapters.NETWORKTableAdapter();
                        VMwareCandidateDataSet.CANDIDATESDataTable candidatesDT = new VMwareCandidateDataSet.CANDIDATESDataTable();
                        candidatesTA.Fill(candidatesDT);

                        StringBuilder sbFilter = new StringBuilder();

                        sbFilter.AppendFormat("NAME = \'{0}\'", (string)candidate);

                        System.Data.DataRow[] drCandidates = candidatesDT.Select(sbFilter.ToString());

                        int candidateID = (int)drCandidates[0]["CANDIDATES_ID"];


                        cpuTA.Insert((decimal)wmiquery.PercentProcessorTime, (int)candidateID);
                        diskTA.Insert(wmiquery.DiskReadPerSec.ToString(), wmiquery.DiskWritePerSec.ToString(), (int)candidateID);
                        memoryTA.Insert((int)wmiquery.AvailableMBytes, (int)wmiquery.PageFaultsPerSec, (decimal)wmiquery.PercentCommittedBytesInUse, (int)candidateID);
                        networkTA.Insert((int)wmiquery.BytesReceivedPerSec, (int)wmiquery.BytesSentPerSec, (int)candidateID);

                        System.Threading.Monitor.Enter(oThreadLock);
                        try
                        {
                            operationCount++;
                        }
                        finally
                        {
                            System.Threading.Monitor.Exit(oThreadLock);
                        }
                        System.Threading.Thread.Sleep(1000 * 60 * 5); //sleep for 5 minutes
                    }
                    else
                        return;
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine(ex.Message);
                }
            }
        }
        public int progressCount
        {
            get
            {
                return operationCount;
            }
        }
    }
}
